

$.fn.gmaps = function(options) {
		
		// Default values
		var params = $.extend({}, $.gmaps.defaults, options);
		
		return this.each(function() {
			// Create Map
			params.element = this;
			$.gmaps.initMap(params);
			
		});
 	};


$.gmaps = {
	map:false,
	bounds:false,
	markers:[],
	points:[],
	geocoder:false,
	params:false,
	defaults:{
		center: {
			latitude:'34.43036357495847',
			longitude:'-119.76904392242432',
			address:''
		},
		zoom:4,
		fitToPoints:false,
		geolocate:{
			geolocate:false,
			marker:{
				show:false,
				image:false
			}
		},
		markers:[],
		mapType:'hybrid ',
		controls: {
			pan:{
				show:false,
				position:'top_right'
			},
			zoom:{
				show:true,
				style:'default',
				position:'left_center'
			},
			mapType:{
				show:true,
				style:'default',
				position:'bottom_center'
			},
			scale:{
				show:false,
				position:'top_left'				
			},
			streetView:{
				show:false,
				position:'left_top'
			}
		},
		events:{
			click:false,
			dblclick:false,
			mouseup:false,
			mousedown:false,
			mouseover:false,
			mouseout:false		
		},
		places:{
			search:false,
			center:false,
			radius:false,
			searchBox:false,
			placeChanged:{
				action:false,
				zoom:7
			}
		}
	},
	
	initMap: function(params) {
		var config = {
			mapTypeId:false,
			zoom:false,
			center:false,
			panControl:false,
			panControlOptions: {
				position:false
			},
			mapTypeControl:false,
			mapTypeControlOptions: {
				position:false,
				style:false
			},
			zoomControl:false,
			zoomControlOptions: {
				position:false,
				style:false
			},
			scaleControl:false,
			scaleControlOptions: {
				position:false
			},
			streetViewControl:false,
			streetViewControlOptions: {
				position:false
			}
		};
		$.gmaps.params = params;
		// Initialize geocoder
		$.gmaps.geocoder = new google.maps.Geocoder();
		
		// Map Type
		config.mapTypeId = $.gmaps.parseType(params.mapType);
		
		// Zoom
		config.zoom = params.zoom;
		
		// Center
		if(params.center.latitude && params.center.longitude) {
			config.center = $.gmaps.parsePoint(params.center.latitude, params.center.longitude);
		}
		else {
			config.center = $.gmaps.parsePoint($.gmaps.defaults.center.latitude, $.gmaps.defaults.center.longitude);
		}
		
		
		// Controls
		if(params.controls.pan) {
			config.panControl = params.controls.pan.show;
			config.panControlOptions.position = $.gmaps.parseControlPosition(params.controls.pan.position);
		}
		if(params.controls.mapType) {
			config.mapTypeControl = params.controls.mapType.show;
			config.mapTypeControlOptions.position = $.gmaps.parseControlPosition(params.controls.mapType.position);
			config.mapTypeControlOptions.style = $.gmaps.parseTypeControlStyle(params.controls.mapType.style);
		}
		if(params.controls.zoom) {
			config.zoomControl = params.controls.zoom.show;
			config.zoomControlOptions.position = $.gmaps.parseControlPosition(params.controls.zoom.position);
			config.zoomControlOptions.style = $.gmaps.parseZoomControlStyle(params.controls.zoom.style);
		}
		if(params.controls.scale) {
			config.scaleControl = params.controls.scale.show;
			config.scaleControlOptions.position = $.gmaps.parseControlPosition(params.controls.scale.position);
		}
		if(params.controls.streetView) {
			config.streetViewControl = params.controls.streetView.show;
			config.streetViewControlOptions.position = $.gmaps.parseControlPosition(params.controls.streetView.position);
		
		}
		
		
		
		
		
		
		
		$.gmaps.map = new google.maps.Map(params.element, config);
		
		
		// Listeners
		if(typeof(params.onClick) == 'function') {
			google.maps.event.addListener($.gmaps.map, 'click', function(event) {
				params.onClick(event);
			});
		}
		
		// Geolocate
		if(params.geolocate.geolocate) {
			$.gmaps.geolocate(params.geolocate);
		}
		if(params.center.address) {
			$.gmaps.geocode(params.center.address, function(results) {
				$.gmaps.map.setCenter(results[0].geometry.location);
			});
		}
		
		
		// Markers
		$.gmaps.parseMarkers(params.markers);
		google.maps.event.addListener($.gmaps.map, 'bounds_changed', function() {
        	$.gmaps.bounds = $.gmaps.map.getBounds();
        	
      	});
		
		$.gmaps.parsePlaces(params.places);
		
		
		
		
	},
	addMarker: function(marker) {
		var i = $.gmaps.markers.length;
		$.gmaps.initMarker(marker, i);
	},
	initMarker: function(marker, i) {
		$.gmaps.markers[i] = new google.maps.Marker($.gmaps.createMarker(marker));
		$.gmaps.markers[i].markerNum = i;
		$.gmaps.markers[i].position = marker.position;
		$.gmaps.markers[i].onClick = marker.onClick;
		$.gmaps.markers[i].onMouseOver = marker.onMouseOver;
		$.gmaps.markers[i].onMouseOut = marker.onMouseOut;
		$.gmaps.markers[i].onDoubleClick = marker.onDoubleClick;
		$.gmaps.markers[i].onMouseUp = marker.onMouseUp;
		$.gmaps.markers[i].onMouseDown = marker.onMouseDown;
		
		
		if(marker.info) {
			$.gmaps.markers[i].infoWindow = new google.maps.InfoWindow({
				content:marker.info.html
			});
			google.maps.event.addListener($.gmaps.markers[i], 'click', function() {
				this.infoWindow.open($.gmaps.map, this);
				
			});
			if(marker.info.autoOpen == true) {
				$.gmaps.markers[i].infoWindow.open($.gmaps.map, $.gmaps.markers[i]);
			}
		}
		
		// Listeners
		if(typeof($.gmaps.markers[i].onMouseOver) == 'function') {
			google.maps.event.addListener($.gmaps.markers[i], 'mouseover', function() {
				this.onMouseOver();
			});
		}
		if(typeof($.gmaps.markers[i].onMouseOut) == 'function') {
			google.maps.event.addListener($.gmaps.markers[i], 'mouseout', function() {
				this.onMouseOut();
			});
		}
		if(typeof($.gmaps.markers[i].onClick) == 'function') {
			google.maps.event.addListener($.gmaps.markers[i], 'click', function() {
				this.onClick();
			});
		}
		if(typeof($.gmaps.markers[i].onDoubleClick) == 'function') {
			google.maps.event.addListener($.gmaps.markers[i], 'dblclick', function() {
				this.onDoubleClick();
			});
		}
		if(typeof($.gmaps.markers[i].onMouseUp) == 'function') {
			google.maps.event.addListener($.gmaps.markers[i], 'mouseup', function() {
				this.onMouseUp();
			});
		}
		if(typeof($.gmaps.markers[i].onMouseDown) == 'function') {
			google.maps.event.addListener($.gmaps.markers[i], 'mousedown', function() {
				this.onMouseDown();
			});
		}
		
		if($.gmaps.params.fitToPoints) {
			var latlngbounds = new google.maps.LatLngBounds( );
			for ( var i = 0; i < $.gmaps.points.length; i++ ) {
  				latlngbounds.extend( $.gmaps.points[ i ] );
			}
			$.gmaps.map.fitBounds( latlngbounds );
		}
	},
	geocodeMarker: function(marker, i) {
		$.gmaps.geocoder.geocode({
				address:marker.address
		
			},
			function(results, status) {
				$.gmaps.points.push(results[0].geometry.location);
				marker.position = results[0].geometry.location;
				$.gmaps.initMarker(marker, i);
				
				if($.gmaps.params.onGeocode) {
					$.gmaps.params.onGeocode(results[0].geometry.location);
				}
			}
		);
	},
	geocode: function(address, success) {
		$.gmaps.geocoder.geocode({
			address:address
		},
		function(results, status) {
			success(results, status);
		});
	},
	parseMarkers: function(markers, callback) {
		
		for(var i=0;i<markers.length;i++) {
		
			// Create the marker and set its listener functions to avoid namespace confusion
			if(markers[i].latitude && markers[i].longitude) {
				var position = $.gmaps.parsePoint(markers[i].latitude, markers[i].longitude);
				markers[i].position = position;
				$.gmaps.points.push(position);
				$.gmaps.initMarker(markers[i], i);
			}
			else if(markers[i].address) {
				// Geocode
				$.gmaps.geocodeMarker(markers[i], i);
				
			}
			
			
			
		}
		if(callback) {
			callback();
		}
		
	},
	createMarker: function(marker) {
		var gmapMarker = {
			map: $.gmaps.map,
			position:marker.position,
			draggable:marker.draggable,	
			icon:marker.image
		};
		gmapMarker.animation = $.gmaps.parseMarkerAnimation(marker.animation);
		
		return gmapMarker;
	},
	parseMarkerAnimation:function(animation) {
		var markerAnimation;
		switch(animation) {
			case 'drop':
				markerAnimation = google.maps.Animation.DROP;
				break;
			case 'bounce':
				markerAnimation = google.maps.Animation.BOUNCE;
				break;
			default:
				markerAnimation = false;
				break;
		}
		return markerAnimation;
	},
	geolocate: function(params) {
		if(navigator.geolocation) {
    		browserSupportFlag = true;
    		navigator.geolocation.getCurrentPosition(function(position) {
    			var position = $.gmaps.parsePoint(position.coords.latitude, position.coords.longitude);
    			$.gmaps.map.setCenter(position);
    			if(params.marker) {
	    			if(params.marker.show) {
	    				var marker = new google.maps.Marker({
							map: $.gmaps.map,
							position:position
						});
						if(params.marker.image) {
							marker.icon = params.marker.image;
						}
	    				$.gmaps.markers.push(marker);
						$.gmaps.points.push(position);
	    			}
	    		}
    		}, function() {
    			$.gmaps.geolocationError();
    		});
       		
 	 	} 
 	  	
      	else {
      		$.gmaps.geolocationError();
      	}
      		
	},
	geolocationError: function() {
		alert('Error getting your location');
	},
	parsePoint: function(latitude, longitude) {
		return new google.maps.LatLng(latitude, longitude);
	},
	parseType: function(type) {
		var gmapType;
		switch(type) { 
			case 'roadmap':
			default:
				gmapType = google.maps.MapTypeId.ROADMAP;
				break;
			case 'satellite':	
				gmapType = google.maps.MapTypeId.SATELLITE;
				break;
			case 'hybrid':
				gmapType = google.maps.MapTypeId.HYBRID;
				break;
			case 'terrain':
				gmapType = google.maps.MapTypeId.TERRAIN;
				break;
		}
		return gmapType;
	},
	parseZoomControlStyle: function(style) {
		var styleType;
		switch(style) {
			case 'small':
				styleType = google.maps.ZoomControlStyle.SMALL;
				break;
			case 'large':
				styleType = google.maps.ZoomControlStyle.LARGE;
				break;
			case 'default':
			default:
				styleType = google.maps.ZoomControlStyle.DEFAULT;
				break;
		}
		return styleType;
	},
	parseTypeControlStyle: function(style) {
		var styleType;
		switch(style) {
			case 'horizontal_bar':
				styleType = google.maps.MapTypeControlStyle.HORIZONTAL_BAR;
				break;
			case 'dropdown_menu':
				styleType = google.maps.MapTypeControlStyle.DROPDOWN_MENU;
				break;
			case 'default':
			default:
				styleType = google.maps.MapTypeControlStyle.DEFAULT;
				break;
		}
		return styleType;
	},
	parseControlPosition: function(position) {
		var positionReturn;
		switch(position) {
			default:
			case 'top_left':
				positionReturn = google.maps.ControlPosition.TOP_LEFT;
				break;
			case 'left_top':
				positionReturn = google.maps.ControlPosition.LEFT_TOP;
				break;
			case 'left_center':
				positionReturn = google.maps.ControlPosition.LEFT_CENTER;
				break;
			case 'left_bottom':
				positionReturn = google.maps.ControlPosition.LEFT_BOTTOM;
				break;
			case 'bottom_left':
				positionReturn = google.maps.ControlPosition.BOTTOM_LEFT;
				break;
			case 'bottom_center':
				positionReturn = google.maps.ControlPosition.BOTTOM_CENTER;
				break;
			case 'bottom_right':
				positionReturn = google.maps.ControlPosition.BOTTOM_RIGHT;
				break;
			case 'right_bottom':
				positionReturn = google.maps.ControlPosition.RIGHT_BOTTOM;
				break;
			case 'right_center':
				positionReturn = google.maps.ControlPosition.RIGHT_CENTER;
				break;
			case 'right_top':
				positionReturn = google.maps.ControlPosition.RIGHT_TOP;
				break;
			case 'top_right':
				positionReturn = google.maps.ControlPosition.TOP_RIGHT;
				break;
			case 'top_center':
				positionReturn = google.maps.ControlPosition.TOP_CENTER;
				break;
		}
		return positionReturn;
	},
	parsePlaces: function(places) {
		if(places.searchBox) {
			var autocompleteOptions = {
				types:['establishment']	
			}
			var autocomplete = new google.maps.places.Autocomplete(document.getElementById(places.searchBox), autocompleteOptions);
			autocomplete.bindTo('bounds', $.gmaps.map);
			switch(places.placeChanged.action) {
				case 'marker':
					google.maps.event.addListener(autocomplete, 'place_changed', function() {
						$.gmaps.clearOverlays();
						var place = autocomplete.getPlace();
						if (place.geometry.viewport) {
							$.gmaps.map.fitBounds(place.geometry.viewport);
						} 
						else {
						    $.gmaps.map.setCenter(place.geometry.location);
						    $.gmaps.map.setZoom(places.placeChanged.zoom);
						}
						var length = $.gmaps.markers.length;
						$.gmaps.markers[length] = new google.maps.Marker({
							map: $.gmaps.map,
							position:place.geometry.location
						});
						$.gmaps.markers[length].infoWindow = new google.maps.InfoWindow({
							content:place.name
						});
						$.gmaps.markers[length].infoWindow.open($.gmaps.map, $.gmaps.markers[length]);
						if(places.placeChanged.callback) {
							places.placeChanged.callback(place);
						}
					});
					break;
			}
		}
	},
	clearOverlays: function() {
		for(var i=0; i < $.gmaps.markers.length; i++) {
        	$.gmaps.markers[i].setMap(null);
    	}
    	$.gmaps.markers = new Array();
	}

}